<?php
/**
 * Main ArchivePress plugin class file
 *
 * This file contains the main plugin classes
 * @author University of London Computer Centre
 * @version 1.4.0 - Release Candidate 2
 * @package ArchivePress
 */
/**
 * This class provide a solid option data structure
 * for the ArchivePress plugin
 * @package ArchivePress
 * @subpackage classes
 */
class ArchivePressOptions {
    /**#@+
     * Constants
     */
    /**
     * Just a "yes"
     */
	const YES							= "yes";
    /**
     * Just a "no"
     */
	const NO							= "no";

    /**
     * Post Comments status -> closed
     */
	const COMMENTS_CLOSED				= "closed";
    /**
     * Post Comments status -> open
     */
	const COMMENTS_OPEN					= "open";

    /**
     * Fetched Post status -> publish
     */
	const POST_PUBLISH					= "publish";
    /**
     * Fetched Post status -> draft
     */
	const POST_DRAFT					= "draft";
    /**
     * Fetched Post status -> pending
     */
	const POST_PENDING					= "pending";

    /**
     * Kind of crontab used by the plugin -> WordPress Crontab
     */
	const CRON_WPCRON					= "wpcron";
    /**
     * Kind of crontab used by the plugin -> Web Crontab
     */
	const CRON_WEBCRON					= "webcron";
    /**
     * Kind of crontab used by the plugin -> Linux/Unix Crontab
     */
	const CRON_UNIXCRON					= "unixcron";

    /**
     * Plugin Version
     */
	const PLUGIN_VERSION				= "1.3.0";

    /**
     * Plugin New table name -> feed table
     */
	const PLUGIN_FEEDSTABLE_NAME		= "feeds";
    /**
     * Plugin New table name -> feed links table
     */
	const PLUGIN_FEEDLINKSTABLE_NAME	= "feed_links";
    /**
     * Plugin New table name -> meta table
     */
	const PLUGIN_FEEDMETATABLE_NAME		= "feed_meta";
    /**
     * Plugin New table name -> option table
     */
	const PLUGIN_FEEDOPTIONSTABLE_NAME	= "feed_options";
    /**
     * Plugin New table name -> user table
     */
	const PLUGIN_FEEDUSERSTABLE_NAME	= "feed_users";
    /**
     * Plugin New table name -> log table
     */
	const PLUGIN_LOGTABLE_NAME			= "logs";

    /**
     * Feed protocol -> RSS
     */
	const FEED_PROTOCOL_RSS		= "rss";
    /**
     * Rss protocol version -> 0.90
     */
		const RSS_VERSION_0_90	= "0.90";
    /**
     * Rss protocol version -> 0.91
     */
		const RSS_VERSION_0_91	= "0.91";
    /**
     * Rss protocol version -> 1.0
     */
		const RSS_VERSION_1_0	= "1.0";
    /**
     * Rss protocol version -> 2.0
     */
		const RSS_VERSION_2_0	= "2.0";

    /**
     * Feed protocol -> ATOM
     */
	const FEED_PROTOCOL_ATOM	= "atom";
    /**
     * Atom protocol version -> 0.3
     */
		const ATOM_VERSION_0_3	= "0.3";
    /**
     * Atom protocol version -> 1.0
     */
		const ATOM_VERSION_1_0	= "1.0";

    /**
     * Fetching time interval -> daily
     */
	const FETCH_INTERVAL_DAILY	= 86400;
    /**
     * Fetching time interval -> twice a day
     */
	const FETCH_INTERVAL_BID	= 43200;
    /**
     * Fetching time interval -> tree times a day
     */
	const FETCH_INTERVAL_TID	= 28800;
    /**
     * Fetching time interval -> four times a day
     */
	const FETCH_INTERVAL_FOURTAD= 21600;
    /**
     * Fetching time interval -> hourly
     */
	const FETCH_INTERVAL_HOURLY	= 3600;

    /**
     * Fedd name
     */
	const FEED_NAME				= "name";
    /**
     * Admin user name
     */
	const ADMIN_USER			= "user";
    /**
     * Use default category option
     */
	const USE_DEF_CAT			= "useDefaultCategory";

    /**
     * Default not stripped html tags
     */
	const DEFAULT_HTML_TAGS		= "<div><p><h1><h2><h3><h4><h5><h6><ul><ol><li><dl><dt><dd><address><hr><pre><blockquote><center><ins><del><a><span><bdo><br><em><strong><dfn><code><samp><kbd><bar><cite><abbr><acronym><q><sub><sup><tt><i><b><big><small><u><s><strike><basefont><font><object><param><img><table><caption><colgroup><col><thead><tfoot><tbody><tr><th><td><embed>";

    /**
     * Default Contributors category name
     */
	const DEFAULT_CONTRIBUTORS	= "Contributors";


    /**#@+
     * Default PLUGIN options
     */
    /**
     * Plugin Version
     * @access public
     * @var string
     */
	public $pluginVersion		= self::PLUGIN_VERSION;
    /**
     * Feed table name
     * @access public
     * @var string
     */
	public $feedsTableName		= self::PLUGIN_FEEDSTABLE_NAME;
    /**
     * Feed Links table name
     * @access public
     * @var string
     */
	public $feedLinksTableName	= self::PLUGIN_FEEDLINKSTABLE_NAME;
    /**
     * Meta table name
     * @access public
     * @var string
     */
	public $feedMetaTableName	= self::PLUGIN_FEEDMETATABLE_NAME;
    /**
     * Plugin Options table name
     * @access public
     * @var string
     */
	public $feedOptionsTableName= self::PLUGIN_FEEDOPTIONSTABLE_NAME;
    /**
     * User table name
     * @access public
     * @var string
     */
	public $feedUsersTableName	= self::PLUGIN_FEEDUSERSTABLE_NAME;
    /**
     * Log table name
     * @access public
     * @var string
     */
	public $logTableName		= self::PLUGIN_LOGTABLE_NAME;
    /**
     * Embed media option
     * @access public
     * @var string
     */
	public $embedMedia			= self::YES;
    /**
     * Kind of crontab to use
     * @access public
     * @var string
     */
	public $cronType			= self::CRON_WPCRON;
    /**
     * Crontab key (to allow the cron jobs)
     * @access public
     * @var string
     */
	public $cronKey				= "";
    /**
     * Plugin crontab
     * @access public
     * @var string
     */
	public $cron				= "";

    /**#@+
     * Default FEED options
     */
    /**
     * Default feed protocol
     * @access public
     * @var string
     */
	public $defFeedProtocol		= self::FEED_PROTOCOL_RSS;
    /**
     * Default RSS Protocol Version
     * @access public
     * @var string
     */
	public $defRssVersion		= self::RSS_VERSION_2_0;
    /**
     * Default ATOM Protocol Version
     * @access public
     * @var string
     */
	public $defAtomVersion		= self::ATOM_VERSION_1_0;
    /**
     * Default fetching interval (for crontab)
     * @access public
     * @var integer
     */
	public $defFeedFetchInt		= self::FETCH_INTERVAL_DAILY;
    /**
     * Indicates if the feed added has to be already active
     * @access public
     * @var string
     */
	public $justAddedIsActive	= self::YES;
    /**
     * Indicates if show to the wp admin user what the plugin will do
     * BEFORE to do it
     * @access public
     * @var string
     */
	public $showWhatWillDo		= self::YES;
    /**
     * Indicates if the plugin has to follow the feed permalinks
     * to download the ORIGINAL post content
     * @access public
     * @var string
     */
	public $followPermaLink		= self::NO;
    /**
     * Indicates if the plugin has to keep the original post author
     * @access public
     * @var string
     */
	public $keepPostAuth		= self::YES;
    /**
     * Otherwise indicate here the default post author
     * @access public
     * @var string
     */
	public $defAuthor			= self::FEED_NAME;
    /**
     * Indicates if the plugin has to keep the feed categories
     * @access public
     * @var string
     */
	public $keepPostCategories	= self::YES;
    /**
     * Otherwise indicates wich is the default category
     * @access public
     * @var string
     */
	public $defCategory			= self::USE_DEF_CAT;
    /**
     * Indicates if the plugin has to try to auto-tagging
     * the fetched content
     * @access public
     * @var string
     */
	public $tryAutoTag			= self::NO;
    /**
     * If you want to use Yahoo to auto-tag a content
     * here you have to provide a Yahoo Key
     * for your domain
     * @access public
     * @var string
     */
	public $YahooKey			= NULL;
    /**
     * Indicates if use the feed categories as post tags
     * @access public
     * @var string
     */
	public $useCategoriesAsTags	= self::YES;
    /**
     * Indicates the just added post status
     * @access public
     * @var string
     */
	public $defPostStatus		= self::POST_PUBLISH;
    /**
     * Indicates the comment status for the just added posts
     * @access public
     * @var string
     */
	public $defCommentsStatus	= self::COMMENTS_CLOSED;
    /**
     * Indicates if the plugin has to fetch also the post comments
     * @access public
     * @var string
     */
	public $postFetchComments	= self::YES;
    /**
     * Indicates if the plugin has to try to fetch the
     * comments for TypePad standard blogs
     * @access public
     * @var string
     */
	public $tryTypePadStandard	= self::NO;
    /**
     * Indicates if the fetched comments are approved by default
     * Otherwise the plugins uses the WP general options
     * @access public
     * @var string
     */
	public $areCommentsApproved	= self::YES;
    /**
     * List of html allowed tags
     * for the fetched posts and comments
     * @access public
     * @var string
     */
	public $htmlAllowedTags		= self::DEFAULT_HTML_TAGS;
    /**
     * Indicates if the plugin has to save also the contributors (Blogs)
     * as WP LINKS
     * @access public
     * @var string
     */
	public $saveContributors	= self::YES;
    /**
     * Default link category for the contributors
     * (if saved)
     * @access public
     * @var string
     */
	public $defContributorLink	= self::DEFAULT_CONTRIBUTORS;
    /**
     * Indicates if the plugin has to try to find
     * the excerpt for a fetched post
     * @access public
     * @var string
     */
	public $tryToFindExcerpt	= self::YES;

    /**#@+
     * Default LOG options
     */
    /**
     * indicates if the Log system is running or not
     * @access public
     * @var string
     */
	public $defLogStatus		= ArchivePressLog::LOG_OFF;
    /**
     * Indicates which notifications save
     * @access public
     * @var string
     */
	public $defLogLevel			= ArchivePressLog::LOG_BASIC;
    /**
     * Default notifications shown by the dashboard widget
     * IMPORTANT: if $defLogLevel is LOG_BASIC
     * ONLY the BASIC notifications are saved
     * and so only them are SHOWN inside the dashboard
     * @access public
     * @var string
     */
	public $log_widget_show		= ArchivePressLog::LOG_BASIC;
    /**
     * Default dashboard widget log table rows
     * @access public
     * @var string
     */
	public $log_widget_items	= 10;

    /**#@+
     * PRIVATE options
     */
    /**
     * Indicates if the WP admin can DELETE all (plugin files, posts, comments, meta, ...)
     * @access public
     * @var string
     */
	public $pluginDelIsAllowed	= self::NO;
    /**
     * Indicates how many times the plugin has to try
     * to find TypePad blog comments
     * @access public
     * @var string
     */
	public $tryTypePadAttempts	= 10;
}

/**
* This class is the core plugin class
* @package ArchivePress
* @subpackage classes
*/
class ArchivePress {
    /**
     * Plugin options
     * @access public
     * @var ArchivePressOptions
     */
	public $options;
    /**
     * last added feed
     * @access public
     * @var string
     */
	public $lastAdded;
    /**
     * feed protocol (the last checked)
     * @access public
     * @var string
     */
	public $lastFeedCheckedProt;
    /**
     * feed protocol version (the last checked)
     * @access public
     * @var string
     */
	public $lastFeedCheckedVers;
    /**
     * last url tested
     * @access public
     * @var string
     */
	public $lastFeedCheckedUrl;
    /**
     * last blog link
     * @access public
     * @var string
     */
	public $lastFeedCheckedLink;

    /**
     * feed reader class
     * @access private
     * @var FeedReader
     */
	private $FeedReader = NULL;
    /**
     * global wp db class
     * @access private
     * @var Wpdb
     */
	private $wpdb;
    /**
     * logging class
     * @access private
     * @var ArchivePressLog
     */
	private $Log;

    /**
     * feed table
     * @access private
     * @var string
     */
	private $feedTable;
    /**
     * feed options table
     * @access private
     * @var string
     */
	private $feedOptions;
    /**
     * feed meta table
     * @access private
     * @var string
     */
	private $feedMeta;
    /**
     * feed links table
     * @access private
     * @var string
     */
	private $feedLinks;
    /**
     * user table
     * @access private
     * @var string
     */
	private $feedUsers;


    /**
     * init everything
     *
     * @global Wpdb $wpdb
     */
	function __construct(ArchivePressOptions $options = NULL){
		// Init Options
		if(isset($options)){
			$this->options = $options;
		}else{ // uses default options
			$this->options = new ArchivePressOptions();
		}

		// set global db connection (and class)
		global $wpdb;
		$this->wpdb = $wpdb;

		// Internationalization
		$this->options->defContributorLink = __($this->options->defContributorLink,ARCHIVEPRESS);

		// bring user saved options inside the class (override default settings with the user's one)
		$this->refreshClassOptions();

		// db table names
		$this->feedTable	= $this->wpdb->prefix . WP_ARCHIVEPRESS_PREFIX . $this->options->feedsTableName;
		$this->feedLinks	= $this->wpdb->prefix . WP_ARCHIVEPRESS_PREFIX . $this->options->feedLinksTableName;
		$this->feedOptions	= $this->wpdb->prefix . WP_ARCHIVEPRESS_PREFIX . $this->options->feedOptionsTableName;
		$this->feedMeta		= $this->wpdb->prefix . WP_ARCHIVEPRESS_PREFIX . $this->options->feedMetaTableName;
		$this->feedUsers	= $this->wpdb->prefix . WP_ARCHIVEPRESS_PREFIX . $this->options->feedUsersTableName;
		$this->logTable		= $this->wpdb->prefix . WP_ARCHIVEPRESS_PREFIX . $this->options->logTableName;

		// log class
		global $ArchivePressLog;
		$ArchivePressLog	= new ArchivePressLog($this->logTable,$this->options->defLogStatus,$this->options->defLogLevel);
		$this->Log			= $ArchivePressLog;

		// feed reader class
		$this->FeedReader = new FeedReader();
	}

    /**
     * check if a link provided is already a feed
     *
     * @param string $url The feed (to check) url
     * @param string $content The feed content
     * @return bool
     */
	function isFeed($url,$content=NULL){
		$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("START: check url '%s'",ARCHIVEPRESS), $url));

		// save feed link (to use it to add a new feed later)
		$lastFeedCheckedUrl = $url;
		try {
		    // not a feed link
			if( $this->FeedReader->isFeed($url,$content) == false ){
				$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("END: the url '%s',  is not a feed url.",ARCHIVEPRESS), $url));
				return false;
			} else {
			    // it's a feed link: find the protocol
				if($this->FeedReader->isRss){
					$this->lastFeedCheckedProt = ArchivePressOptions::FEED_PROTOCOL_RSS;
					$this->lastFeedCheckedVers = $this->FeedReader->feedVersion;
				} else{
					$this->lastFeedCheckedProt = ArchivePressOptions::FEED_PROTOCOL_ATOM;
					$this->lastFeedCheckedVers = ArchivePressOptions::ATOM_VERSION_1_0;
				}
				// save feed datas (to use it to add a new feed later)
				$this->lastFeedCheckedUrl  = $url;
				$this->lastFeedCheckedLink = $this->FeedReader->blogUrl;
				$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("END: the url '%s',  is a feed url.",ARCHIVEPRESS), $url));
				return true;
			}
		} catch (Exception $e) {
			// page not found or other curl errors
			$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("%s: page not found!=",ARCHIVEPRESS), $url));
			throw new Exception(__('Page not found',ARCHIVEPRESS));
		}
	}

    /**
     * add the last feed link checked
     *
     * @param string $name The feed name
     * @param bool $checkDatabaseBefore indicates if a db check is required to avoid duplication
     * @param string $isComment Indicates if the feed is a blog feed or a comment feed
     * @return bool
     */
	function addLastCheckedFeed($name,$checkDatabaseBefore = true,$isComment="no"){
		$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("START: add feed '%s'",ARCHIVEPRESS), $name));

		// if required check if the feed is already inside the db
		if($checkDatabaseBefore){
			$myrows = $this->wpdb->get_row( "SELECT id FROM ".$this->feedLinks." WHERE url = '".$this->wpdb->escape($this->lastFeedCheckedUrl)."' ", OBJECT );
			// if already added
			if(isset($myrows)) {
				throw new Exception(__('Feed already exists',ARCHIVEPRESS));
				$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("Feed '%s' already exists.",ARCHIVEPRESS), $name));
			}
		}
		// check before if the name is UNIQUE
		$myrows = $this->wpdb->get_row( "SELECT id FROM ".$this->feedTable." WHERE name = '".$this->wpdb->escape($name)."' ", OBJECT);
		// if exists already
		if(isset($myrows)) {
			throw new Exception(__('Feed name already exists',ARCHIVEPRESS));
			$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("Feed name '%s' already exists.",ARCHIVEPRESS), $name));
		}

		// add it into the database
		// feed
		$this->wpdb->query("INSERT INTO ".$this->feedTable."
							(id,name,url,protocol,version,feed_date,last_update,is_comment,active,last_fetched)
							VALUES ('','".$this->wpdb->escape($name)."','".$this->wpdb->escape($this->lastFeedCheckedUrl)."','".$this->wpdb->escape($this->lastFeedCheckedProt)."','".$this->wpdb->escape($this->lastFeedCheckedVers)."',FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."),FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."),'".$this->wpdb->escape($isComment)."','".$this->wpdb->escape($this->options->justAddedIsActive)."',NULL) ");
		$myrows = $this->wpdb->get_row( "SELECT id FROM ".$this->feedTable." WHERE url = '".$this->wpdb->escape($this->lastFeedCheckedUrl)."' ", ARRAY_A);
		// options
		// fetch interval
		$this->wpdb->query("INSERT INTO ".$this->feedOptions."
							(id,feed_id,name,value)
							VALUES ('','".(int)$myrows['id']."','interval','".$this->wpdb->escape($this->options->defFeedFetchInt)."')");

		if($isComment == "no") { // POST FEED SPECIFIC OPTIONS
    		// fetch also comments
    		$this->wpdb->query("INSERT INTO ".$this->feedOptions."
    							(id,feed_id,name,value)
    							VALUES ('','".(int)$myrows['id']."','comments','".$this->wpdb->escape($this->options->postFetchComments)."')");
    		// is new (to allow feed upload)
    		$this->wpdb->query("INSERT INTO ".$this->feedOptions."
    								(id,feed_id,name,value)
    								VALUES ('','".(int)$myrows['id']."','is_new','yes')");
    		// follow permalinks
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "followPermaLink','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "followPermaLink"))."')");
            // embed media
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "embedMedia','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "embedMedia"))."')");
            // default post status
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "defPostStatus','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "defPostStatus"))."')");
            // excerpt
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt"))."')");

            // comment status
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "defCommentsStatus','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "defCommentsStatus"))."')");

		} else { // COMMENT FEED SPECIFIC OPTIONS
            // approve or not comments by default
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "areCommentsApproved','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "areCommentsApproved"))."')");

        }
		// meta
		// Added when feed fetched
		// This allows the plugin to
		// log metadata changes

		// links
		$this->wpdb->query("INSERT INTO ".$this->feedLinks."
							(id,feed_id,url,is_the_one_in_use)
							VALUES ('','".(int)$myrows['id']."','".$this->wpdb->escape($this->lastFeedCheckedUrl)."','yes')");


		// if required save also as Contributor
		if( ($this->options->saveContributors == ArchivePressOptions::YES) && ($isComment == "no") ){
			require_once(ABSPATH . "/wp-admin/includes/bookmark.php");
			// get contributor link category
			$category = $this->options->defContributorLink;
			$term = get_term_by( 'name', sanitize_title($category), 'link_category',ARRAY_A );
			if($term === false){
				$term = wp_insert_term( $category, 'link_category' );
			}
			$link_id = wp_insert_link(array("link_name" => $this->cleanInput($name), "link_url" => $this->lastFeedCheckedLink ));
			// HACK to update the link category properly
			$oldDefCat = get_option("default_link_category");
			update_option("default_link_category",(int)$term["term_id"]);
			wp_set_link_cats( $link_id );
			update_option("default_link_category",$oldDefCat);
			// END: HACK to update the link category properly

			// save link ID as feed option
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "contributorId','".(int)$link_id."')");

		}

		$this->lastAdded = (int)$myrows['id'];

		$this->Log->logIt(ArchivePressLog::LOG_BASIC,sprintf(__("Feed '%s' successfully added.",ARCHIVEPRESS), $name));
		return true;
	}

    /**
     * add a feed starting from many links (they are the ones found with the autodiscovery procedure)
     *
     * @param array $feeds The feed links
     * @param string $url The main feed url
     * @param string $name The feed name
     * @return bool OR array if not possible to take a decision
     */
	function addFeed(array $feeds,$url,$name){
		$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("START: add feed from url: '%s'",ARCHIVEPRESS), $url));

		$firstFeed = array();
		$otherFeeds = array();
		// for each link I get the first feed
		// then I compare all the first feeds to see if
		// they are the same in different protols (like rss and atom)
		// or if they are different feeds (maybe posts and comments)
		// if DIFFERENT PROTOCOLS> add the feed with the default protocol
		// else ASK to the user
		for($i=0;$i<count($feeds);$i++){
			try {
				$first = array();
				$first = $this->FeedReader->getFirstFeed($feeds[$i]);

				if($i == 0){
					// I add the first
					$first['url'] = $feeds[$i];
					array_push($firstFeed,$first);
				} else if( ($first['title'] != $firstFeed[count($firstFeed)-1]['title']) && ($first['link'] != $firstFeed[count($firstFeed)-1]['link']) ){
					// I check the others
					$first['url'] = $feeds[$i];
					array_push($firstFeed,$first);
				} else if($firstFeed[count($firstFeed)-1]['protocol'] != $this->options->defFeedProtocol){
					// if the new feed is the same I have to keep the one
					// with the default protocol
					$item = array_pop($firstFeed);
					array_push($otherFeeds,$item);
					$first['url'] = $feeds[$i];
					array_push($firstFeed,$first);
				} else {
					$first['url'] = $feeds[$i];
					array_push($otherFeeds,$first);
				}
			} catch (Exception $e) {
				// page not found or other curl errors
				$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("%s: page not found!=",ARCHIVEPRESS), $first['url']));
			}
		}
		$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("%d feed links found.",ARCHIVEPRESS), count($firstFeed)));

		if(count($firstFeed)==1){
			// add the feed
			// check before if the name is UNIQUE
			$myrows = $this->wpdb->get_row( "SELECT id FROM ".$this->feedTable." WHERE name = '".$this->wpdb->escape($name)."' ", OBJECT);
			// if exists already
			if(isset($myrows)) {
				$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("Feed name '%s' already exists.",ARCHIVEPRESS), $name));
				throw new Exception(__('Feed name already exists',ARCHIVEPRESS));
				return false;
			}

			// 1. the selected one
			$this->wpdb->query("INSERT INTO ".$this->feedTable."
								(id,name,url,protocol,version,feed_date,last_update,is_comment,active,last_fetched)
								VALUES ('','".$this->wpdb->escape($name)."','".$this->wpdb->escape($url)."','".$this->wpdb->escape($firstFeed[0]["protocol"])."','".$this->wpdb->escape($firstFeed[0]["version"])."',FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."),FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."),'no','".$this->wpdb->escape($this->options->justAddedIsActive)."',NULL) ");
			$myrows = $this->wpdb->get_row( "SELECT id FROM ".$this->feedTable." WHERE url = '".$this->wpdb->escape($url)."' ", ARRAY_A);
			// options
			// fetch interval
			$this->wpdb->query("INSERT INTO ".$this->feedOptions."
								(id,feed_id,name,value)
								VALUES ('','".(int)$myrows['id']."','interval','".$this->wpdb->escape($this->options->defFeedFetchInt)."')");
			// fetch also comments
			$this->wpdb->query("INSERT INTO ".$this->feedOptions."
								(id,feed_id,name,value)
								VALUES ('','".(int)$myrows['id']."','comments','".$this->wpdb->escape($this->options->postFetchComments)."')");
			// is new (to allow feed upload)
			$this->wpdb->query("INSERT INTO ".$this->feedOptions."
								(id,feed_id,name,value)
								VALUES ('','".(int)$myrows['id']."','is_new','yes')");
            // follow permalinks
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "followPermaLink','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "followPermaLink"))."')");
            // embed media
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "embedMedia','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "embedMedia"))."')");
            // default post status
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "defPostStatus','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "defPostStatus"))."')");
            // excerpt
            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                    (id,feed_id,name,value)
                                    VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt','".$this->wpdb->escape(get_option(WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt"))."')");


			// meta
			// Added when feed fetched
            // This allows the plugin to
            // log metadata changes

			// links
			$this->wpdb->query("INSERT INTO ".$this->feedLinks."
								(id,feed_id,url,is_the_one_in_use)
								VALUES ('','".(int)$myrows['id']."','".$this->wpdb->escape($firstFeed[0]["url"])."','yes')");
			// 2. other links
			for($i=0;$i<count($otherFeeds);$i++){
				$this->wpdb->query("INSERT INTO ".$this->feedLinks."
									(id,feed_id,url,is_the_one_in_use)
									VALUES ('','".(int)$myrows['id']."','".$this->wpdb->escape($otherFeeds[$i]["url"])."','no')");
			}

			// if required save also as Contributor
			if($this->options->saveContributors == ArchivePressOptions::YES){
				require_once(ABSPATH . "/wp-admin/includes/bookmark.php");
				// get contributor link category
				$category = $this->options->defContributorLink;
				$term = get_term_by( 'name', sanitize_title($category), 'link_category',ARRAY_A );
				if($term === false){
					$term = wp_insert_term( $category, 'link_category' );
				}
				$link_id = wp_insert_link(array("link_name" => $this->cleanInput($name), "link_url" => $url ));
				// HACK to update the link category properly
				$oldDefCat = get_option("default_link_category");
				update_option("default_link_category",(int)$term["term_id"]);
				wp_set_link_cats( $link_id );
				update_option("default_link_category",$oldDefCat);
				// END: HACK to update the link category properly


                // save link ID as feed option
                $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                        (id,feed_id,name,value)
                                        VALUES ('','".(int)$myrows['id']."','".WP_ARCHIVEPRESS_PREFIX . "contributorId','".(int)$link_id."')");
			}


			$this->Log->logIt(ArchivePressLog::LOG_BASIC,sprintf(__("Feed '%s' successfully added.",ARCHIVEPRESS), $name));
			return true;
		}else {
			return $feeds;
		}
	}

    /**
     * Check if a feed was already previously added
     *
     * @param array $feeds The feed links
     * @return bool
     */
	function isFeedNew(array $feeds){
		for($i=0;$i<count($feeds);$i++){
			// check if it is already added [database]
			$myrows = $this->wpdb->get_row( "SELECT id FROM ".$this->feedLinks." WHERE url = '".$this->wpdb->escape($feeds[$i])."' ", OBJECT );
			// if already added
			if(isset($myrows))
				return false;
		}
		return true;
	}

    /**
     * fetch feed procedure
     *
     * @param array $feed The feed to fetch
     */
	public function fetchFeed(array $feed) {
		$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("START: fetch feed '%s' (%s)",ARCHIVEPRESS), $feed["name"], $feed["url"]));

		require_once(ABSPATH . WPINC . '/registration.php');

		// load Custom Feed Options
		$this->loadCustomOptions((int)$feed['id']);

		// update feed status: it is not new anymore
		// is new (to allow feed upload)
		// it's less expensive to ask before: a selection is faster than an update!
		$value= $this->wpdb->get_var($this->wpdb->prepare("SELECT value FROM ".$this->feedOptions." WHERE name = %s AND feed_id = %d", "is_new",(int)$feed['id']));
		if($value == "yes"){
			$this->wpdb->query("UPDATE ".$this->feedOptions."
								SET value = 'no'
								WHERE name = 'is_new' AND feed_id = '".(int)$feed['id']."'");
		}

		$posts = array();

		try {
			if(array_key_exists("file",$feed)){
				$file = $feed["file"];
			} else {
				$file = NULL;
			}
			$posts = $this->FeedReader->fetch($feed["url"],$feed["protocol"],$feed["last_fetched"],NULL,$file);
			if(count($posts) > 0){
				// update last fetched and last update time
				$this->wpdb->query("UPDATE ".$this->feedTable." SET last_fetched='".$this->wpdb->escape($posts[0]["lastFetched"])."', last_update=FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s')).") WHERE id='".(int)$feed["id"]."'");

				// add metadata
				// 1. look for metadata
				$feed_id = (int)$feed["id"];
				$value = $this->wpdb->get_var($this->wpdb->prepare("SELECT value FROM ".$this->feedMeta." WHERE feed_id = %d", $feed_id));
				if(!$value){
					// not found --> add
					$this->wpdb->query("INSERT INTO ".$this->feedMeta."
										(id,feed_id,value,meta_date)
										VALUES ('','".(int)$feed_id."','".$this->wpdb->escape($posts[0]["metadata"])."',FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."))");
				} else if (unserialize($posts[0]["metadata"]) !== unserialize($value)) {
					// 2. metadata found: if not changed --> do nothing else add (this is a metadata log)
					$this->wpdb->query("INSERT INTO ".$this->feedMeta."
										(id,feed_id,value,meta_date)
										VALUES ('','".(int)$feed_id."','".$this->wpdb->escape($posts[0]["metadata"])."',FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."))");
				}


				// typepad comments option
				if(($this->options->tryTypePadStandard == ArchivePressOptions::YES) && ($this->options->postFetchComments == ArchivePressOptions::YES) ){
					$isTypePad = $this->wpdb->get_var($this->wpdb->prepare("SELECT value FROM ".$this->feedOptions." WHERE feed_id = %d AND name = %s", $feed_id,"isTypePad"));
					if($isTypePad){
						if($isTypePad == "yes"){
							$isTypePad = true;
						}else {
							$isTypePad = false;
							$typePadCounter = $this->wpdb->get_var($this->wpdb->prepare("SELECT value FROM ".$this->feedOptions." WHERE feed_id = %d AND name = %s", $feed_id,"TypePadCounter"));
						}
					} else {
						$isTypePad = false;
						$typePadCounter = 0;
						$this->wpdb->query("INSERT INTO ".$this->feedOptions."
								(id,feed_id,name,value)
								VALUES ('','".(int)$feed_id."','TypePadCounter','".$this->wpdb->escape($typePadCounter)."')");
						$this->wpdb->query("INSERT INTO ".$this->feedOptions."
								(id,feed_id,name,value)
								VALUES ('','".(int)$feed_id."','isTypePad','no')");
					}

				}

				// insert posts
				foreach($posts as $post) {
					// AUTHOR
					$user_id = "";
					if(($this->options->keepPostAuth == ArchivePressOptions::YES) && ($post["author"] != "") && (strtolower($post["author"]) != "admin") ) {
						$post["author"] = sanitize_user($post["author"],true);
					} else if(($this->options->keepPostAuth == ArchivePressOptions::YES) && (strtolower($post["author"]) != "admin") ) {
						// DON'T USE ADMIN
						$post["author"] = sanitize_user($post["category"],true);
					} else if(($this->options->keepPostAuth == ArchivePressOptions::NO) || ($post["author"] != "")){
						// 2 options: use the category or use the admin author
						if($this->options->defAuthor == ArchivePressOptions::FEED_NAME) {
							$post["author"] = sanitize_user($post["category"],true);
						} else if($this->options->defAuthor == ArchivePressOptions::ADMIN_USER) {
							$post["author"] = "admin";
						} else {
							$user_id = (int)$this->options->defAuthor;
						}
					}
					if($user_id == "") {
						$user_id = username_exists( $post["author"].sanitize_user("@".str_replace(" ","",substr($post["category"],0,6))) );
					}
					$isNewUser = false;
					if ( !isset($user_id)) {
						$random_password = wp_generate_password( 12, false );
						$user_email = $this->getNewMail();
						if(array_key_exists("email",$post)) {
							$user_email = $post["email"];
						}
						// as username I use the name plus an original blog identifier
						// to prevent duplicate
						$userName = $post["author"].sanitize_user("@".str_replace(" ","",substr($post["category"],0,6)));
						$user_id = wp_create_user( $userName, $random_password, $user_email );
						// modify now the Public Name, using the original user name
						wp_update_user(array("ID" => $user_id,"user_url" => $post["author_url"],"display_name" => $post["author"]) );
						$isNewUser = true;
					}
					// CATEGORIES
					if($this->options->keepPostCategories == ArchivePressOptions::YES) {
						// uses the feed title as post category
						$category_id = get_cat_id($post["category"]);
						if ( !$category_id ) {
							require_once(ABSPATH . "/wp-admin/includes/taxonomy.php");
							$category_id = wp_create_category($post["category"], 0);
							wp_update_term( $category_id, 'category', array("description"=>$post["subtitle"]) );
						}
					} else if ($this->options->defCategory == ArchivePressOptions::USE_DEF_CAT) {
						// uses the default category
						$category_id = get_option('default_category');
					} else {
						// uses another category
						$category_id = (int)$this->options->defCategory;
					}
					$category = array();
					array_push($category,$category_id);
					// TAGS
					if(count($post["tags"])>0){
						$tags = implode(", ",$post["tags"]);
					}else{
						$tags = "";
					}
					// DATES
					$dates = array();
					$dates = $this->getDates($post["pubDate"],$feed["protocol"]);
					// UPDATE DATES
					if(array_key_exists("upDate",$post)){
						$updates = array();
						$updates = $this->getDates($post["upDate"],$feed["protocol"]);
					}

					// update content:
					// 1. fix relative links
					// 2. update links in case they are pointing to already added posts
					$internalLinks = $post["internalLinks"];
					for($i=0;$i<count($internalLinks);$i++){
						$link_to_check = $internalLinks[$i];
						// check if the link is pointing on a already added post
						$post_id = $this->wpdb->get_var($this->wpdb->prepare("SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_value = %s", $link_to_check));
						if($post_id){
							// update link
							$post["content"] = str_replace($link_to_check,get_permalink( $post_id ),$post["content"]);
						}
					}

					// CHECK IF IS NEW OR IF IS AN UPDATE
					$meta_value = $post["link"];
					$post_id = $this->wpdb->get_var($this->wpdb->prepare("SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_value = %s", $meta_value));
					// if not already added
					if(!$post_id) {
						// ADD POST
						$newPost = array();
						$newPost["post_status"]		= $this->options->defPostStatus;
						$newPost["comment_status"] 	= $this->options->defCommentsStatus;
						$newPost["post_author"] 	= $user_id;
						$newPost["post_category"] 	= $category;
						$newPost["post_content"] 	= $post["content"];
						$newPost["post_excerpt"]	= $post["excerpt"];
						$newPost["post_date"] 		= $dates["date"];
						$newPost["post_date_gmt"] 	= $dates["gmt"];
						$newPost["post_name"] 		= sanitize_title($post["title"]);
						$newPost["post_title"] 		= $post["title"];
						$newPost["post_type"] 		= 'post';
						$newPost["tags_input"] 		= $tags;
						$post_id = wp_insert_post( $newPost );

						// ATTACHMENTS
						if(array_key_exists("media",$post)){
							require_once(ABSPATH . "/wp-admin/includes/image.php");
							foreach($post["media"] as $media) {
								if($media["type"] == "img"){
									$attach_id = wp_insert_attachment( $newPost, $media["path"], $post_id );
									$attach_data = wp_generate_attachment_metadata( $attach_id, $media["path"] );
									wp_update_attachment_metadata( $attach_id,  $attach_data );
									// original meta link
									add_post_meta($attach_id, WP_ARCHIVEPRESS_PREFIX . 'ori_media_link', $media["oldUrl"]);
									// original post id
									add_post_meta($attach_id, WP_ARCHIVEPRESS_PREFIX . 'attached_post_id', $post_id);
								}
							}
						}


						// POST META DATA
						// is syndacated
						add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'is_syndacated', 'yes');
						// original url
						add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'original_url', $post["link"]);
						// fetching date
						add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'fetch_date', date("Y-m-d H:i:s"));
						// feed id
						add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'feed_id', $feed["id"]);
						// feed guid
						add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'feed_guid', $post["lastFetched"]);

						// IF REQUIRED: ADD COMMENTS FEED
						if($this->options->postFetchComments == ArchivePressOptions::YES){
							// SPECIAL CASE: Blogger DOESN'T include the link inside
							// the post item, BUT inside the post page
							// TO DISCOVER it I have to
							// 1. get ALL the feed links from the original post page
							// 2. remove the ones are about thblog (I have them already inside the db)
							// 3. add the last feed link: it is the comments one!
							// PS: this is just for BLOGGER, in the other cases it won't work
							if($post["comments"] == ""){
								$feeds = array();
								try {
									$feeds = FeedAutoDiscovery::getFeedLinks($post["link"]);
									for($i=0;$i<count($feeds);$i++){
										$link_count = $this->wpdb->get_var("SELECT COUNT(*) FROM ".$this->feedLinks." WHERE url = '".$this->wpdb->escape($feeds[$i])."' ");
										if($link_count == 0){
											$post["comments"] = $feeds[$i];
											break;
										}
									}
								} catch (Exception $e) {
									$this->Log->logIt(ArchivePressLog::LOG_DEBUG,__($e->getMessage(),ARCHIVEPRESS));
								}

							}
							if($post["comments"] != ""){
								if($this->isFeed($post["comments"])){
									// DON'T add link as contributor
									$oldOption = $this->options->saveContributors;
									$this->options->saveContributors = ArchivePressOptions::NO;
									$this->addLastCheckedFeed(sprintf(__("Comments on '%s'",ARCHIVEPRESS), $newPost["post_title"]),true,"yes");
									$this->options->saveContributors = $oldOption;
									// comments feed link
									add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'comments', $this->lastAdded);
									// add parent feed ID to comment options
									// get comment id
                                    $comment_id = $this->getLastFeedId();
								    // set parent blog id
                                    $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                                        (id,feed_id,name,value)
                                                        VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX . "parentFeed','".(int)$feed["id"]."')");
								}
							}else if($this->options->tryTypePadStandard == ArchivePressOptions::YES) { // if required
								// Try TypePad STANDARD BLOG procedure
								// this means if it has custom fields it won't work!
								if(!$isTypePad){
									// number of attempts not reached
									if($typePadCounter < $this->options->tryTypePadAttempts) {
										if($this->FeedReader->isTypePad($post["link"])){
											$this->wpdb->query("UPDATE ".$this->feedOptions."
																SET value = 'yes'
																WHERE feed_id = '".(int)$feed_id."'
																AND name = 'isTypePad'");
											$this->lastFeedCheckedProt = "html";
											$this->lastFeedCheckedVers = "html";
											$this->lastFeedCheckedUrl  = $post["link"];
											$this->lastFeedCheckedLink = $post["link"];
											// DON'T add link as contributor
											$oldOption = $this->options->saveContributors;
											$this->options->saveContributors = ArchivePressOptions::NO;
											$this->addLastCheckedFeed(sprintf(__("Comments on '%s'",ARCHIVEPRESS), $newPost["post_title"]),true,"yes");
											$this->options->saveContributors = $oldOption;
											// comments feed link
											add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'comments', $this->lastAdded);
											// add parent feed ID to comment options
                                            // get comment id
                                            $comment_id = $this->getLastFeedId();
                                            // set parent blog id
                                            $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                                                (id,feed_id,name,value)
                                                                VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX . "parentFeed','".(int)$feed["id"]."')");

											$isTypePad = true;
										} else {
											// update TypePad Option counter
											$typePadCounter++;
											$this->wpdb->query("UPDATE ".$this->feedOptions."
																SET value = '".$this->wpdb->escape($typePadCounter)."'
																WHERE feed_id = '".(int)$feed_id."'
																AND name = 'TypePadCounter'");
										}
									}
								} else {
									$this->lastFeedCheckedProt = "html";
									$this->lastFeedCheckedVers = "html";
									$this->lastFeedCheckedUrl  = $post["link"];
									$this->lastFeedCheckedLink = $post["link"];
									// DON'T add link as contributor
									$oldOption = $this->options->saveContributors;
									$this->options->saveContributors = ArchivePressOptions::NO;
									$this->addLastCheckedFeed(sprintf(__("Comments on '%s'",ARCHIVEPRESS), $newPost["post_title"]),true,"yes");
									$this->options->saveContributors = $oldOption;
									// comments feed link
									add_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'comments', $this->lastAdded);
									// add parent feed ID to comment options
                                    // get comment id
                                    $comment_id = $this->getLastFeedId();
                                    // set parent blog id
                                    $this->wpdb->query("INSERT INTO ".$this->feedOptions."
                                                        (id,feed_id,name,value)
                                                        VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX . "parentFeed','".(int)$feed["id"]."')");
								}
							}
						}

					} else {
						// UPDATE POST PROCEDURE
						$newPost = array();
						$newPost['ID'] = $post_id;
						$newPost["post_status"]		= $this->options->defPostStatus;
						$newPost["comment_status"] 	= $this->options->defCommentsStatus;
						$newPost["post_author"] 	= $user_id;
						$newPost["post_category"] 	= $category;
						$newPost["post_content"] 	= $post["content"];
						$newPost["post_excerpt"]	= $post["excerpt"];
						if(isset($updates)){
							$newPost["post_date"] 		= $updates["date"];
							$newPost["post_date_gmt"] 	= $updates["gmt"];
						}else {
							$newPost["post_date"] 		= $dates["date"];
							$newPost["post_date_gmt"] 	= $dates["gmt"];
						}
						$newPost["post_name"] 		= sanitize_title($post["title"]);
						$newPost["post_title"] 		= $post["title"];
						$newPost["post_type"] 		= 'post';
						$newPost["tags_input"] 		= $tags;
						wp_update_post( $newPost );

						// ATTACHMENTS: NOT WORKING HERE....
						/*
								if(array_key_exists("media",$post)){
									require_once(ABSPATH . "/wp-admin/includes/image.php");
									foreach($post["media"] as $media) {
										if($media["type"] == "img"){
											$attach_id = wp_insert_attachment( $newPost, $media["path"], $post_id );
											$attach_data = wp_generate_attachment_metadata( $attach_id, $media["path"] );
											wp_update_attachment_metadata( $attach_id,  $attach_data );
											// original meta link
											add_post_meta($attach_id, WP_ARCHIVEPRESS_PREFIX . 'ori_media_link', $media["oldUrl"]);
											// original post id
											add_post_meta($attach_id, WP_ARCHIVEPRESS_PREFIX . 'attached_post_id', $post_id);
										}
									}
								}
						*/

						// POST META
						update_post_meta($post_id, WP_ARCHIVEPRESS_PREFIX . 'fetch_date', date("Y-m-d H:i:s"));

					}

					// add archivepress user data
					if($isNewUser) {
						// NOW IN wp_usermeta
						/*
							$this->wpdb->query("INSERT INTO ".$this->feedUsers."
												(id,feed_id,ori_username,add_post_id,add_date)
												VALUES ('','".$feed["id"]."','".$post["originalAuthor"]."','".$post_id."',FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."))");
						*/
						// USER META
						// feed_id
						update_usermeta( $user_id, WP_ARCHIVEPRESS_PREFIX . 'feed_id', $feed["id"] );
						// ori_username
						update_usermeta( $user_id, WP_ARCHIVEPRESS_PREFIX . 'ori_username', $post["originalAuthor"] );
						// add_post_id
						update_usermeta( $user_id, WP_ARCHIVEPRESS_PREFIX . 'add_post_id', $post_id );
					}

				}
			}else {
				// update last_update
				$this->wpdb->query("UPDATE ".$this->feedTable." SET last_update=FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s')).") WHERE id='".(int)$feed["id"]."'");
			}
			$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(_n("%d posts added","%d post added",count($posts),ARCHIVEPRESS), count($posts)));

			// reload Default Feed Options
            $this->refreshClassOptions();

			return count($posts);
		} catch (Exception $e){
		    // reload Default Feed Options
            $this->refreshClassOptions();

			$this->Log->logIt(ArchivePressLog::LOG_BASIC,__($e->getMessage(),ARCHIVEPRESS));
		}
	}

    /**
     * fetch feed comments
     *
     * @param integer $feed_id The feed ID (NO the comment feed ID, but the MAIN feed ID)
     * @param bool $activeOnly Indicates if fetch only active comment feeds
     * @param bool $isComment Indicates if $feed_id is refering to a comment feed
     */
	public function fetchFeedComments($feed_id = 0, $activeOnly = false, $isComment = false) {
	    $totComments = 0;
		// search feed URLs
		$active = "";
		if($activeOnly) {
		    $active = " AND active = 'yes' ";
		}

		if($isComment) {
            $myrows = $this->wpdb->get_results( "SELECT feed.id, feed.name, feed.protocol, feed.last_fetched, links.url
                                                FROM ".$this->feedTable." AS feed
                                                LEFT JOIN ".$this->feedLinks." AS links ON feed.id = links.feed_id
                                                WHERE feed.active='yes' AND links.is_the_one_in_use = 'yes'
                                                AND feed.is_comment='yes'
                                                ".$active."
                                                AND feed.id = '".(int)$feed_id."' ", ARRAY_A );
		} else {
    		$myrows = $this->wpdb->get_results( "SELECT feed.id, feed.name, feed.protocol, feed.last_fetched, links.url
    											FROM ".$this->feedTable." AS feed
    											LEFT JOIN ".$this->feedLinks." AS links ON feed.id = links.feed_id
    											WHERE feed.active='yes' AND links.is_the_one_in_use = 'yes'
    											AND feed.is_comment='yes'
    											".$active."
    											AND feed.id IN
    											(SELECT meta_value FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."comments'
    											AND post_id IN (SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."feed_id' AND meta_value = '".(int)$feed_id."'  ) )
    		 									", ARRAY_A );
		}
		if($myrows) {
			foreach($myrows as $row){
                // for each feed: try to fetch comments
				$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(__("START: fetch feed '%s' (%s)",ARCHIVEPRESS), $row["name"], $row["url"]));

				// load Custom Feed Options
                $this->loadCustomOptions($row['id']);

				$posts = array();

				try {
					if($row["protocol"] != "html"){
					    // fetch RSS or Atom feed
						$comments = $this->FeedReader->fetch($row["url"],$row["protocol"],$row["last_fetched"]);
					} else {
					    // TypePad standard blogs special procedure
						$comments = $this->FeedReader->fetchTypePadComments($row["url"],$row["last_fetched"]);
					}

					// some new comment found
					if(count($comments) > 0){
						// update last fetched and last update time
						$this->wpdb->query("UPDATE ".$this->feedTable." SET last_fetched='".$this->wpdb->escape($comments[0]["lastFetched"])."', last_update=FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s')).") WHERE id='".(int)$row["id"]."'");

						// process comments
						$post_id = $this->wpdb->get_var("SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."comments' AND meta_value = '".(int)$row["id"]."'");
						foreach($comments as $comment) {
							$dates = array();
							$dates = $this->getDates($comment["pubDate"],$row["protocol"]);
							$email = "";
							if(array_key_exists("email",$comment)){
								$email = $comment["email"];
							}
							$commentdata = array(
											'comment_post_ID'		=> $post_id,
										    'comment_author'		=> $comment["author"],
										    'comment_author_email'	=> $email,
										    'comment_author_url'	=> 'http://',
										    'comment_content'		=> $comment["content"],
										    'comment_author_IP'		=> $_SERVER['REMOTE_ADDR'],
										    'comment_date'			=> $dates["date"],
										    'comment_date_gmt'		=> $dates["gmt"],
											'comment_type'			=> "",
										    'comment_approved'		=> 1
											);
							if($this->options->areCommentsApproved == ArchivePressOptions::YES){
								// insert AUTO APPROVED comment
								$comment_id = wp_insert_comment( $commentdata );
							} else {
								// the comment will follow the wp rules
								$comment_id = wp_new_comment ( $commentdata );
							}
							if($comment_id){
								// metadata
								$this->wpdb->query("INSERT INTO ".$this->wpdb->prefix."commentmeta
													(meta_id,comment_id,meta_key,meta_value)
													VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX."feed_guid','".$this->wpdb->escape($comment["lastFetched"])."')");
								$this->wpdb->query("INSERT INTO ".$this->wpdb->prefix."commentmeta
													(meta_id,comment_id,meta_key,meta_value)
													VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX."feed_id','".(int)$row["id"]."')");
								$this->wpdb->query("INSERT INTO ".$this->wpdb->prefix."commentmeta
													(meta_id,comment_id,meta_key,meta_value)
													VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX."fetch_date',FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s'))."))");
								$this->wpdb->query("INSERT INTO ".$this->wpdb->prefix."commentmeta
													(meta_id,comment_id,meta_key,meta_value)
													VALUES ('','".(int)$comment_id."','".WP_ARCHIVEPRESS_PREFIX."original_url','".$this->wpdb->escape($comment["link"])."')");

							}
						}

						$this->Log->logIt(ArchivePressLog::LOG_DEBUG,sprintf(_n("%d posts added","%d post added",count($posts),ARCHIVEPRESS), count($posts)));
					}else {
						// update last_update
						$this->wpdb->query("UPDATE ".$this->feedTable." SET last_update=FROM_UNIXTIME(".strtotime(date('Y-m-d H:i:s')).") WHERE id='".(int)$row["id"]."'");
					}

                        // update total fetched comments
                        $totComments += count($comments);

				} catch (Exception $e){
				    // reload Default Feed Options
                    $this->refreshClassOptions();

					$this->Log->logIt(ArchivePressLog::LOG_BASIC,__($e->getMessage(),ARCHIVEPRESS));
				}
			}
		}

		// reload Default Feed Options
        $this->refreshClassOptions();

		return $totComments;
	}

    /**
     * get the last added Feed ID
     *
     * @return integer The feed ID
     */
    public function getLastFeedId(){
        return $this->wpdb->get_var($this->wpdb->prepare("SELECT id FROM ".$this->feedTable." ORDER BY id DESC LIMIT 1"));
    }

    /**
     * get feed
     *
     * @param integer $id The feed ID
     * @return array
     */
	public function getFeed($id){
        $sql = "SELECT feed.id, feed.active, feed.name,feed.is_comment, feed.last_update, feed.protocol, feed.last_fetched, links.url
                FROM ".$this->feedTable." AS feed
                LEFT JOIN ".$this->feedLinks." AS links ON feed.id = links.feed_id
                WHERE links.is_the_one_in_use = 'yes' AND feed.id = '".(int)$id."'";
        $myrows = $this->wpdb->get_results($sql, ARRAY_A);
        if(count($myrows) > 0){
            foreach ($myrows as $feed) {
                // add options
                $options = $this->wpdb->get_results("SELECT name, value FROM ".$this->feedOptions." WHERE feed_id = '".(int)$feed["id"]."'", ARRAY_A);
                foreach ($options as $option) {
                    $feed[$option["name"]] = $option["value"];
                }
                return $feed;
            }
        }
	}

    /**
     * get all the feeds
     *
     * @param bool $activesOnly Only ACTIVE feeds
     * @param bool $idsOnly Only the ID
     * @param string $filterName The "search condition" on feed.name
     * @param string $filterProtocol The "search condition" on feed.protocol
     * @param string $limit Limit for the query
     * @return array
     */
	public function getFeeds($activesOnly=false, $idsOnly=false, $filterName = "", $filterProtocol = "", $limit = "", $isComment = "no") {
		$sql;
		if($idsOnly){
			$sql = "SELECT feed.id ";
		} else {
			$sql = "SELECT feed.id, feed.active, feed.name,feed.is_comment, feed.last_update, feed.protocol, feed.last_fetched, links.url ";
		}
		if($filterName != ""){
		    $filterName = $this->wpdb->prepare(" AND feed.name LIKE %s", "%".$filterName."%");
		}
	   if($filterProtocol != ""){
            $filterProtocol = $this->wpdb->prepare(" AND feed.protocol LIKE %s", "%".$filterProtocol."%");
        }
		if($activesOnly){
			$sql .= " FROM ".$this->feedTable." AS feed
					LEFT JOIN ".$this->feedLinks." AS links ON feed.id = links.feed_id
					WHERE feed.active='yes' AND links.is_the_one_in_use = 'yes' AND feed.is_comment = '".$this->wpdb->escape($isComment)."' $filterName $filterProtocol ORDER BY feed.name $limit";
		} else {
			$sql .= " FROM ".$this->feedTable." AS feed
					LEFT JOIN ".$this->feedLinks." AS links ON feed.id = links.feed_id
					WHERE links.is_the_one_in_use = 'yes'  AND feed.is_comment = '".$this->wpdb->escape($isComment)."' $filterName $filterProtocol ORDER BY feed.name $limit";
		}
		$feeds = array();
		$myrows = $this->wpdb->get_results($sql, ARRAY_A);
		if(count($myrows) > 0){
    		foreach ($myrows as $feed) {
    			if(!$idsOnly){
    				// if required add option
    				$options = $this->wpdb->get_results("SELECT name, value FROM ".$this->feedOptions." WHERE feed_id = '".(int)$feed["id"]."'", ARRAY_A);
    				foreach ($options as $option) {
    				    $feed[$option["name"]] = $option["value"];
    				}
    			}
    			array_push($feeds, $feed);
    		}
		}
		return $feeds;
	}

    /**
     * get category original link
     *
     * @param integer $cat_id The category ID
     * @return string
     */
	public function get_blog_link($cat_id){
		$post = get_posts('numberposts=1&category='.(int)$cat_id);
		$post_id = $post[0]->ID;
		$feed_id = get_post_meta($post_id,WP_ARCHIVEPRESS_PREFIX."feed_id", true);
		return $this->wpdb->get_var($this->wpdb->prepare("SELECT url FROM ".$this->feedTable." WHERE id = %d", (int)$feed_id));
	}

    /**
     * get blog numbers
     * @return array
     */
	public function getBlogs(){
		$blogs = array();
		$blogs["total"] = $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(id) FROM ".$this->feedTable." WHERE is_comment = %s", "no"));
		$blogs["active"] = $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(id) FROM ".$this->feedTable." WHERE is_comment = %s AND active= %s", "no","yes"));
		return $blogs;
	}

    /**
     * get comment feed numbers
     * @return array
     */
    public function getCommentFeeds(){
        $blogs = array();
        $blogs["total"] = $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(id) FROM ".$this->feedTable." WHERE is_comment = %s", "yes"));
        $blogs["active"] = $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(id) FROM ".$this->feedTable." WHERE is_comment = %s AND active= %s", "yes","yes"));
        return $blogs;
    }

    /**
     * get post number
     * @return integer
     */
	public function getPosts(){
		return $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(p.ID) FROM ".$this->wpdb->posts." AS p LEFT JOIN ".$this->wpdb->postmeta ." AS m ON p.ID = m.post_id WHERE p.post_type = %s AND m.meta_key LIKE %s", "post",WP_ARCHIVEPRESS_PREFIX."feed_guid"));
	}

    /**
     * get fetched comments count
     * @return integer
     */
	public function getComments(){
		return $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(c.comment_ID) FROM ".$this->wpdb->comments." AS c LEFT JOIN ".$this->wpdb->prefix."commentmeta AS m ON c.comment_ID = m.comment_id WHERE  m.meta_key LIKE %s", WP_ARCHIVEPRESS_PREFIX."feed_guid"));
	}

    /**
     * get fetched post authors count
     * @return integer
     */
	public function getAuthors(){
		return $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(u.ID) FROM ".$this->wpdb->users." AS u LEFT JOIN ".$this->wpdb->usermeta ." AS m ON u.ID = m.user_id WHERE  m.meta_key LIKE %s", WP_ARCHIVEPRESS_PREFIX."ori_username"));
	}

    /**
     * get last fetched
     *
     * @param string $type The type of the element fetched (blog or comment)
     * @return array
     */
	public function getLastFetched($type="blog"){
		$is_comment = "no";
		if($type == "comment")
			$is_comment = "yes";
		$date = array();
		$feeds = $this->wpdb->get_results("SELECT name, last_update FROM ".$this->feedTable." WHERE is_comment='".$is_comment."' ORDER BY last_update DESC LIMIT 1", ARRAY_A);
		if($feeds) {
    		foreach ($feeds as $feed) {
    			$date["blog"] = $feed["name"];
    			$date["datetime"] = $feed["last_update"];
    		}
		}
		return $date;
	}

    /**
     * get next to fetch
     *
     * @param string $type The type of the element to fetch (blog or comment)
     * @return array
     */
	public function getNextToFetch($type="blog"){
		$is_comment = "no";
		if($type == "comment")
			$is_comment = "yes";
		$date = array();
		$date["datetime"] = 999999999999999999;
		$feeds = $this->wpdb->get_results("SELECT f.name, f.last_update,o.value FROM ".$this->feedTable." AS f LEFT JOIN ".$this->feedOptions." AS o ON f.id = o.feed_id WHERE f.is_comment='".$is_comment."' AND o.name='interval'", ARRAY_A);
		if($feeds) {
    		foreach ($feeds as $feed) {

    			if( (strtotime($feed["last_update"])+(int)$feed["value"]) <  $date["datetime"]){
    				$date["blog"] = $feed["name"];
    				$date["datetime"] = (strtotime($feed["last_update"])+$feed["value"]);
    			}
		      }
		}
		return $date;
	}

    /**
     * get the plugin logs
     * @return array
     */
	public function getLogs(){
		$logs = array();
		$where = "";
		if($this->options->log_widget_show == ArchivePressLog::LOG_BASIC){
			$where = "WHERE level = '".ArchivePressLog::LOG_BASIC."'";
		}
		$rows = $this->wpdb->get_results("SELECT * FROM ".$this->logTable." ".$where." ORDER BY log_date DESC LIMIT ".((int)$this->options->log_widget_items)." ", ARRAY_A);
		if($rows) {
    		foreach ($rows as $row) {
    			$log = array();
    			$log["date"] = $row["log_date"];
    			$log["message"] = $row["message"];
    			array_push($logs,$log);
    		}
		}
		return $logs;
	}

    /**
     * get links for a feed
     * @param integer $id The feed Id
     * @return array
     */
    public function getLinksForFeed($id = 0){
        return $this->wpdb->get_results($this->wpdb->prepare("SELECT * FROM ".$this->feedLinks." WHERE feed_id = %d ORDER BY url ", $id), ARRAY_A);
    }

    /**
     * get the category id for a specific feed
     * (because ALL the posts are under the same category)
     * @param integer $id The feed Id
     * @return integer
     */
    public function getCategoryForFeed($id = 0){
        $post_id = $this->wpdb->get_var($this->wpdb->prepare("SELECT p.ID FROM ".$this->wpdb->posts." AS p LEFT JOIN ".$this->wpdb->postmeta ." AS m ON p.ID = m.post_id WHERE p.post_type = %s AND m.meta_key LIKE %s AND m.meta_value = %d", "post", WP_ARCHIVEPRESS_PREFIX."feed_id", $id));
        if($post_id){
            $category = get_the_category($post_id);
            return $category[0]->term_id;
        } else {
            return 1;
        }
    }

    /**
     * get post number for a specific feed
     * @param integer $id The feed Id
     * @return integer
     */
    public function getPostsForFeed($id = 0){
        return $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(p.ID) FROM ".$this->wpdb->posts." AS p LEFT JOIN ".$this->wpdb->postmeta ." AS m ON p.ID = m.post_id WHERE p.post_type = %s AND m.meta_key LIKE %s AND m.meta_value = %d", "post", WP_ARCHIVEPRESS_PREFIX."feed_id", $id));
    }

    /**
     * get post authors for a specific feed
     * @param integer $id The feed Id
     * @return integer
     */
    public function getAuthorsForFeed($id = 0){
        return $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(u.ID) FROM ".$this->wpdb->users." AS u LEFT JOIN ".$this->wpdb->usermeta ." AS m ON u.ID = m.user_id WHERE  m.meta_key LIKE %s AND m.meta_value = %d", WP_ARCHIVEPRESS_PREFIX."feed_id", $id));
    }

    /**
     * get the parent blog feed for a comment feed
     * @param integer $id The comment feed Id
     * @return array
     */
    public function getParentBlogForFeed($id = 0){
        // looking for the post ID
        $post_id = $this->wpdb->get_var($this->wpdb->prepare("SELECT m.post_id FROM ".$this->wpdb->postmeta." AS m WHERE  m.meta_key = %s AND m.meta_value = %d", WP_ARCHIVEPRESS_PREFIX."comments", $id));

        // now looking for the parent feed ID
        $feed_id = $this->wpdb->get_var($this->wpdb->prepare("SELECT meta_value FROM ".$this->wpdb->postmeta." WHERE meta_key = %s AND post_id = %d", WP_ARCHIVEPRESS_PREFIX."feed_id", $post_id ));

        // and finally the feed
        $feed = $this->getFeed($feed_id);

        // add other useful fields
        $feed["post_id"] = $post_id;

        return $feed;
    }

    /**
     * get the comments count for a feed post
     * @param integer $id The post ID
     * @return integer
     */
    public function getCommentCount($id = 0){
        return $this->wpdb->get_var($this->wpdb->prepare("SELECT COUNT(c.comment_ID) FROM ".$this->wpdb->comments." AS c WHERE  c.comment_post_ID = %d", $id));
    }

    /**
     * get last fetch time for a specific feed
     *
     * @param integer $id The feed Id
     * @param string $type The type of the element fetched (blog or comment)
     * @return array
     */
    public function getLastFetchedForFeed($id = 0, $type="blog"){
        $is_comment = "no";
        if($type == "comment")
            $is_comment = "yes";
        $date = array();
        $feeds = $this->wpdb->get_results("SELECT name, last_update FROM ".$this->feedTable." WHERE is_comment='".$is_comment."' AND id = '".(int)$id."'", ARRAY_A);
        if($feeds) {
            foreach ($feeds as $feed) {
                $date["blog"] = $feed["name"];
                $date["datetime"] = $feed["last_update"];
            }
        }
        return $date;
    }

    /**
     * get next fetch time for a specific feed
     *
     * @param integer $id The feed Id
     * @param string $type The type of the element to fetch (blog or comment)
     * @return array
     */
    public function getNextToFetchForFeed($id = 0, $type="blog"){
        $is_comment = "no";
        if($type == "comment")
            $is_comment = "yes";
        $date = array();
        $feeds = $this->wpdb->get_results("SELECT f.name, f.last_update,o.value FROM ".$this->feedTable." AS f LEFT JOIN ".$this->feedOptions." AS o ON f.id = o.feed_id WHERE f.is_comment='".$is_comment."' AND o.name='interval' AND f.id = '".(int)$id."' ", ARRAY_A);
        if($feeds) {
            foreach ($feeds as $feed) {
                $date["blog"] = $feed["name"];
                $date["datetime"] = (strtotime($feed["last_update"])+$feed["value"]);
            }
        }
        return $date;
    }

    /**
     * get feed authors (ONLY for posts)
     *
     * @param integer $filterParentBlog The parent blog (feed) ID
     * @param string $filterUsername Filter on Username
     * @param string $filterOriName Filter on Original Name
     * @param string $limit sql LIMIT
     * @return array
     */
    public function getFilteredAuthors($filterParentBlog = "", $filterUsername = "", $filterOriName = "", $limit = ""){
        require_once(ABSPATH . WPINC . '/user.php');

        $return = array();
        $sql = "";
        if($filterParentBlog != ""){
            $filterParentBlog = $this->wpdb->prepare(" AND meta.meta_key = %s AND meta.meta_value = %d", WP_ARCHIVEPRESS_PREFIX."feed_id", (int)$filterParentBlog);
        }
        if($filterUsername != ""){
            $filterUsername = $this->wpdb->prepare(" AND user.user_login LIKE %s", "%".$filterUsername."%");
        }
        if($filterOriName != ""){
            $filterOriName = $this->wpdb->prepare(" AND meta.meta_key = %s AND meta.meta_value LIKE %s", WP_ARCHIVEPRESS_PREFIX."ori_username", $filterOriName);
        }

        $sql .= "SELECT * FROM ".$this->wpdb->users." AS user
                LEFT JOIN ".$this->wpdb->usermeta." AS meta ON user.ID = meta.user_id
                WHERE user.ID != '1' $filterParentBlog $filterUsername $filterOriName GROUP BY user.ID ORDER BY user.user_login, meta.umeta_id DESC $limit";
        $authors = $this->wpdb->get_results($sql);
        if($authors) {
            // return a better structure
            $id = 0;
            $tmp = array();
            foreach($authors as $author) {
				// save author
				// author data
				$id = $author->ID;
				$tmp["id"]          = $author->ID;
				$tmp["username"]    = $author->user_login;
				if(function_exists("count_user_posts")){ // compatibility
					$tmp["posts"]   = count_user_posts( $author->ID );
				} else {
					$tmp["posts"]   = get_usernumposts( $author->ID );
				}
				// author meta
				$tmp["meta"][WP_ARCHIVEPRESS_PREFIX."ori_username"] = get_usermeta( $id, WP_ARCHIVEPRESS_PREFIX."ori_username" );
				$tmp["meta"][WP_ARCHIVEPRESS_PREFIX."feed_id"] = get_usermeta( $id, WP_ARCHIVEPRESS_PREFIX."feed_id" );
				$tmp["meta"][WP_ARCHIVEPRESS_PREFIX."add_post_id"] = get_usermeta( $id, WP_ARCHIVEPRESS_PREFIX."add_post_id" );
                array_push($return, $tmp);
				$tmp = array();
            }
        }

        return $return;
    }

    /**
     * Get metadata changelog for a specific feed
     *
     * @param integer $id The feed id
     * @return array The metadata changelog
     */
    public function getMetadataChangeLog($id) {
        $changelog = array();

        $metadata = $this->wpdb->get_results($this->wpdb->prepare("SELECT * FROM ".$this->feedMeta."
                                                                   WHERE feed_id = %d ORDER BY meta_date DESC", $id));
        if($metadata) {
            $i = 0;
            $oldmeta = null;
            foreach($metadata as $meta) {
                $log = array();
                $log["id"]          = $meta->id;
                $log["date_time"]   = $meta->meta_date;

                // get changes
                if($i != 0) {
                    $changelog[$i-1]["changes"]     = $this->FeedReader->compareMetadata($meta->value, $oldmeta->value);
                } else {
                    $log["changes"]     = null;
                }

                array_push($changelog, $log);

                $oldmeta = $meta;
                $i++;
            }
        }

        return $changelog;
    }

    /**
     * Get a specific metadata
     *
     * @param integer $id The metadata id
     * @return array The metadata
     */
    public function getMetadata($id) {
        $metadata = array();

        $meta = $this->wpdb->get_results($this->wpdb->prepare("SELECT * FROM ".$this->feedMeta."
                                                               WHERE id = %d", $id));
        if($meta) {
            foreach($meta as $m) {
                $metadata["date_time"]  = $m->meta_date;
                $metadata["value"]      = $this->FeedReader->ReadableMetadata($m->value);
                $metadata["feed_id"]    = $m->feed_id;
            }
        }

        return $metadata;
    }

    /**
     * Set a feed field
     *
     * @param integer $id The feed id
     * @param string $item The field to set
     * @param string $vale The new value
     */
    public function setFeed($id, $item, $value){
        $this->wpdb->query($this->wpdb->prepare("UPDATE ".$this->feedTable."
                                                 SET ".$item." = %s
                                                 WHERE id = %d", $value, $id));
    }

    /**
     * Set a feed option field
     *
     * @param integer $id The feed id
     * @param string $item The field to set
     * @param string $vale The new value
     */
    public function setFeedOption($id, $item, $value){
        $this->wpdb->query($this->wpdb->prepare("UPDATE ".$this->feedOptions."
                                                 SET value = %s
                                                 WHERE name = %s
                                                 AND feed_id = %d", $value, $item, $id));
    }

    /**
     * Set the active link for a feed
     *
     * @param integer $id The feed id
     * @param integer $link the Link id
     */
    public function setActiveLink($id, $link){
        // make ALL inactive
        $this->wpdb->query($this->wpdb->prepare("UPDATE ".$this->feedLinks."
                                                 SET is_the_one_in_use = %s
                                                 WHERE feed_id = %d", "no", $id));
        // set the active one
        $this->wpdb->query($this->wpdb->prepare("UPDATE ".$this->feedLinks."
                                                 SET is_the_one_in_use = %s
                                                 WHERE id = %d
                                                 AND feed_id = %d", "yess", $link, $id));
    }

    /**
     * Reset a feed
     * It means:
     *  remove posts
     *  remove authors
     *  remove comments
     *  remove tags (if posts == 0)
     *  remove categories (if posts == 0)
     *
     * @param integer $id The feed ID
     */
    public function resetFeed($id){
    
    	require_once(ABSPATH . "/wp-admin/includes/user.php");
    
        // RESET FEED
        // reset last fetched and puit it INACTIVE
        $this->wpdb->query($this->wpdb->prepare("UPDATE ".$this->feedTable."
                                                 SET active = %s, last_fetched = %s
                                                 WHERE id = %d", "no", "", (int)$id));
        // delete related feed comments
        $myrows = $this->wpdb->get_results( "SELECT feed.id, feed.name, feed.protocol, feed.last_fetched, links.url
                                            FROM ".$this->feedTable." AS feed
                                            LEFT JOIN ".$this->feedLinks." AS links ON feed.id = links.feed_id
                                            WHERE feed.active='yes' AND links.is_the_one_in_use = 'yes'
                                            AND feed.is_comment='yes'
                                            AND feed.id IN
                                            (SELECT meta_value FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."comments'
                                            AND post_id IN (SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."feed_id' AND meta_value = '".(int)$id."'  ) )
                                            ", ARRAY_A );


        if($myrows) {
            foreach($myrows as $row){
                // feed
                $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedTable."
                                                  WHERE id = %d",  (int)$row["id"]));

                // feed links
                $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedLinks."
                                                  WHERE feed_id = %d",  (int)$row["id"]));

                // feed metadata
                $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedMeta."
                                                  WHERE feed_id = %d",  (int)$row["id"]));

                // feed options
                $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedOptions."
                                                  WHERE feed_id = %d",  (int)$row["id"]));

            }
        }

        // delete metadata
        $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedMeta."
                                          WHERE feed_id = %d",  (int)$id));

        // POSTS, POST METADATA, COMMENTS, COMMENT METADATA AND AUTHORS
        // 1. find archivePress posts
        $myrows = $this->wpdb->get_results("SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."feed_id' AND meta_value = '".(int)$id."'  GROUP BY post_id ", ARRAY_A );
        if($myrows) {
            foreach($myrows as $row){
                // 2. delete post and everything related
                $this->deletePost($row["post_id"]);
            }
        }

        // 2. post authors
        $myrows = $this->wpdb->get_results("SELECT user_id FROM ".$this->wpdb->usermeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."feed_id' AND meta_value = '".(int)$id."' GROUP BY user_id ", ARRAY_A );
        if($myrows) {
            foreach($myrows as $row){
                wp_delete_user( $row["user_id"] );
            }
        }

        // CATEGORIES: remove ALL the categories with no posts (NO the default one of course)
        require_once(ABSPATH . "/wp-admin/includes/taxonomy.php");
        $args = array(
            'type'                     => 'post',
            'child_of'                 => 0,
            'hide_empty'               => false,
            'pad_counts'               => true );
        $categories = get_categories( $args );
        foreach($categories as $category) {
            if($category->category_count == 0) {
                wp_delete_category($category->cat_ID);
            }
        }

        // TAGS: remove ALL the tags with no posts
        $args = array(
            'type'                     => 'post',
            'child_of'                 => 0,
            'hide_empty'               => false,
            'pad_counts'               => true );

        $tags = get_tags( $args );
        foreach($tags as $tag) {
            if($tag->count == 0){
                wp_delete_term($tag->term_id, $tag->taxonomy);
            }
        }

    }

    /**
     * Delete a feed
     * It means:
     *  remove the feed
     *  remove posts
     *  remove authors
     *  remove comments
     *  remove contributor
     *  remove tags (if posts == 0)
     *  remove categories (if posts == 0)
     *
     * @param integer $id The feed ID
     */
    public function deleteFeed($id){
        // RESET FEED (to delete ALL)
        $this->resetFeed((int)$id);

        // delete contributor
        require_once(ABSPATH . "/wp-admin/includes/bookmark.php");
        // get id
        $feed = $this->getFeed((int)$id);
        $link_id = $feed[WP_ARCHIVEPRESS_PREFIX . "contributorId"];
        // remove it
        wp_delete_link($link_id);

        // DELETE FEED (to delete the feed and the feed link)
        // feed
        $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedTable."
                                          WHERE id = %d",  (int)$id));

        // feed links
        $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedLinks."
                                          WHERE feed_id = %d",  (int)$id));
        // feed metadata
        $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedMeta."
                                          WHERE feed_id = %d",  (int)$id));

        // feed options
        $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->feedOptions."
                                          WHERE feed_id = %d",  (int)$id));
    }

    /**
     * Clean output using WP functions
     *
     * @param string $elem String to clean
     * @return string
     */
    public function cleanOutput($elem){
        return wp_specialchars(stripslashes_deep($elem));
    }

    /**
     * Clean input using WP functions
     *
     * @param string $elem String to clean
     * @return string
     */
    public function cleanInput($elem){
        $elem = stripslashes_deep($elem);
        $elem = addslashes($elem);
        $elem = wp_filter_post_kses( $elem ); // calls stripslashes then addslashes
        $elem = stripslashes($elem);
        $elem = esc_html( $elem );
        return $elem;
    }

    /**
     * make something "WP nice"
     *
     * @param string $elem String to make "WP nice"
     * @return string
     */
	private function makeNice($elem){
        $elem = sanitize_title($elem);
        $elem = sanitize_user($elem,false);
        return $elem;
	}

    /**
     * get wp format dates from a pubDate
     *
     * @param string $date The date to convert
     * @param string $prot The feed protocol
     * @return string
     */
	private function getDates($date,$prot){
		$WPdates = array();
		if($prot == ArchivePressOptions::FEED_PROTOCOL_RSS){
			if($date == ""){
				$date = date("D, d M Y H:i:s T");
			}
			$WPdates["date"]	= date("Y-m-d H:i:s",strtotime($date));
			$WPdates["gmt"]		= date("Y-m-d H:i:s",strtotime($date));
		} else {
			if($date == ""){
				$date = date("d M Y H:i:s");
			}
			$WPdates["date"]	= date("Y-m-d H:i:s",strtotime($date));
			$WPdates["gmt"]		= date("Y-m-d H:i:s",strtotime($date));
		}
		return $WPdates;
	}

    /**
     * get a unique email for a new user
     *
     * @return string
     */
	private function getNewMail() {
		$user_info = array();
		// admin email
		$user_info = get_userdata(1);
		$tmp = explode("@",$user_info->user_email);
		$now = time();
		$mail = $now."@".$tmp[1];
		return $mail;
	}

    /**
     * delete a post and everything related to it
     *
     * @param integer $post_id The id of the post to delete
     */
	private function deletePost($post_id = 0){
		// delete media (delete files from the upload folder)
		// a. GET media
		$wud = wp_upload_dir();
		$upload_path = $wud["basedir"];
		$myrows = $this->wpdb->get_results("SELECT meta_value FROM ".$this->wpdb->postmeta." WHERE meta_key like '%attached_file' and post_id = '".(int)$post_id."' ", ARRAY_A );
		if($myrows) {
			foreach($myrows as $row){
				// b. DELETE media
				unlink($upload_path."/".$row["meta_value"]);
			}
		}
		// delete attachment and post (plus their meta and comments)
		$myrows = $this->wpdb->get_results("SELECT meta_value FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."attached_post_id' and post_id = '".(int)$post_id."' ", ARRAY_A );
		if($myrows) {
			foreach($myrows as $row){
				// a. DELETE post (POST ATTACHMENT!)
				wp_delete_attachment( (int)$row["meta_value"], true );
				// b. DELETE attachment
				wp_delete_post( (int)$row["meta_value"], true );
			}
		}

		// delete comment metadata
		// FOR A WP BUG (OR OTHER REASON)
		// THEY ARE NOT DELETED WHEN YOU DELETE A COMMENT
		$myrows = $this->wpdb->get_results("SELECT comment_ID FROM ".$this->wpdb->comments." WHERE comment_post_ID = '".(int)$post_id."' ", ARRAY_A );
        if($myrows) {
            foreach($myrows as $row){
                $this->wpdb->query($this->wpdb->prepare("DELETE FROM ".$this->wpdb->prefix."commentmeta
                                                         WHERE comment_id = %d",  $row["comment_ID"]));
            }
        }

		// finally delete the POST
        wp_delete_post( (int)$post_id, true );
	}

    /**
     * bring user saved options inside the class (override default settings with the user's one)
     */
	private function refreshClassOptions() {
		// do it only if the plugin has been activated at least one time
		$version = get_option(WP_ARCHIVEPRESS_PREFIX . "version");
		if($version != ""){
			$this->options->version				= get_option(WP_ARCHIVEPRESS_PREFIX . "version");
			$this->options->isRunning			= get_option(WP_ARCHIVEPRESS_PREFIX . "isRunning");
			$this->options->feedsTableName		= get_option(WP_ARCHIVEPRESS_PREFIX . "feedsTableName");
			$this->options->feedLinksTableName	= get_option(WP_ARCHIVEPRESS_PREFIX . "feedLinksTableName");
			$this->options->feedMetaTableName	= get_option(WP_ARCHIVEPRESS_PREFIX . "feedMetaTableName");
			$this->options->feedOptionsTableName= get_option(WP_ARCHIVEPRESS_PREFIX . "feedOptionsTableName");
			$this->options->feedUsersTableName	= get_option(WP_ARCHIVEPRESS_PREFIX . "feedUsersTableName");
			$this->options->logTableName		= get_option(WP_ARCHIVEPRESS_PREFIX . "logTableName");
			$this->options->blogs				= get_option(WP_ARCHIVEPRESS_PREFIX . "blogs");
			$this->options->authors				= get_option(WP_ARCHIVEPRESS_PREFIX . "authors");
			$this->options->archives			= get_option(WP_ARCHIVEPRESS_PREFIX . "archives");
			$this->options->tags				= get_option(WP_ARCHIVEPRESS_PREFIX . "tags");

			// FEED OPTIONS
			$this->options->defFeedProtocol		= get_option(WP_ARCHIVEPRESS_PREFIX . "defFeedProtocol");
			$this->options->defRssVersion		= get_option(WP_ARCHIVEPRESS_PREFIX . "defRssVersion");
			$this->options->defAtomVersion		= get_option(WP_ARCHIVEPRESS_PREFIX . "defAtomVersion");
			$this->options->defFeedFetchInt		= get_option(WP_ARCHIVEPRESS_PREFIX . "defFeedFetchInt");
			$this->options->justAddedIsActive	= get_option(WP_ARCHIVEPRESS_PREFIX . "justAddedIsActive");
			$this->options->showWhatWillDo		= get_option(WP_ARCHIVEPRESS_PREFIX . "showWhatWillDo");
			$this->options->followPermaLink		= get_option(WP_ARCHIVEPRESS_PREFIX . "followPermaLink");
			$this->options->embedMedia			= get_option(WP_ARCHIVEPRESS_PREFIX . "embedMedia");
			$this->options->keepPostAuth		= get_option(WP_ARCHIVEPRESS_PREFIX . "keepPostAuth");
			$this->options->defAuthor			= get_option(WP_ARCHIVEPRESS_PREFIX . "defAuthor");
			$this->options->keepPostCategories	= get_option(WP_ARCHIVEPRESS_PREFIX . "keepPostCategories");
			$this->options->defCategory			= get_option(WP_ARCHIVEPRESS_PREFIX . "defCategory");
			$this->options->tryAutoTag			= get_option(WP_ARCHIVEPRESS_PREFIX . "tryAutoTag");
			$this->options->YahooKey			= get_option(WP_ARCHIVEPRESS_PREFIX . "YahooKey");
			$this->options->useCategoriesAsTags	= get_option(WP_ARCHIVEPRESS_PREFIX . "useCategoriesAsTags");
			$this->options->defPostStatus		= get_option(WP_ARCHIVEPRESS_PREFIX . "defPostStatus");
			$this->options->defCommentsStatus	= get_option(WP_ARCHIVEPRESS_PREFIX . "defCommentsStatus");
			$this->options->postFetchComments	= get_option(WP_ARCHIVEPRESS_PREFIX . "postFetchComments");
			$this->options->tryTypePadStandard	= get_option(WP_ARCHIVEPRESS_PREFIX . "tryTypePadStandard");
			$this->options->areCommentsApproved	= get_option(WP_ARCHIVEPRESS_PREFIX . "areCommentsApproved");
			$this->options->htmlAllowedTags		= get_option(WP_ARCHIVEPRESS_PREFIX . "htmlAllowedTags");
			$this->options->saveContributors	= get_option(WP_ARCHIVEPRESS_PREFIX . "saveContributors");
			$this->options->defContributorLink	= get_option(WP_ARCHIVEPRESS_PREFIX . "defContributorLink");
			$this->options->tryToFindExcerpt	= get_option(WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt");
			$this->options->cronType			= get_option(WP_ARCHIVEPRESS_PREFIX . "cronType");
			$this->options->cronKey				= get_option(WP_ARCHIVEPRESS_PREFIX . "cronKey");
			$this->options->cron				= get_option(WP_ARCHIVEPRESS_PREFIX . "cron");

			// LOG OPTIONS
			$this->options->defLogStatus		= get_option(WP_ARCHIVEPRESS_PREFIX . "defLogStatus");
			$this->options->defLogLevel			= get_option(WP_ARCHIVEPRESS_PREFIX . "defLogLevel");
			$this->options->log_widget_show		= get_option(WP_ARCHIVEPRESS_PREFIX . "log_widget_show");
			$this->options->log_widget_items	= get_option(WP_ARCHIVEPRESS_PREFIX . "log_widget_items");

			// PRIVATE OPTIONS
			$this->options->pluginDelIsAllowed	= get_option(WP_ARCHIVEPRESS_PREFIX . "pluginDelIsAllowed");
			$this->options->tryTypePadAttempts	= get_option(WP_ARCHIVEPRESS_PREFIX . "tryTypePadAttempts");


		}
	}

    /**
     * load Custom Options (for each feed / comment)
     * @param integer $feed_id The Feed ID
     */
	private function loadCustomOptions($feed_id) {
        $options = $this->wpdb->get_results($this->wpdb->prepare("SELECT name,value FROM ".$this->feedOptions." WHERE feed_id = %d ", (int)$feed_id ), ARRAY_A );
        if($options) {
            foreach($options as $opt) {
                $key = str_replace(WP_ARCHIVEPRESS_PREFIX, "", $opt["name"]);
                if(array_key_exists($key, $this->options)) {
                    $this->options->$key = $opt["value"];
                }
            }
        }
	}

    /**
     * set temporary options (to DONT use $_SESSION)
     * @param string $name The option name
     * @param string $value The option value
     */
	public function setTmpOption($name, $value) {
        update_option("TMP".$name."TMP", $value);
	}

    /**
     * get a temporary option (to DONT use $_SESSION)
     * DELETING THE VALUE FROM THE DB
     * @param string $name The option name
     * @return string  The option value
     */
    public function getTmpOption($name) {
        $opt = get_option("TMP".$name."TMP");
        //delete_option("TMP".$name."TMP");
        return $opt;
    }

    /**
     * remove a temporary option (to DONT use $_SESSION)
     * @param string $name The option name
     */
    public function deleteTmpOption($name) {
        delete_option("TMP".$name."TMP");
    }


    /**
     * Plugin Activation (also for reActivation after a deactivation or a deletion)
     */
	public function Activate(){
		// check version in wp options to see if this is the first Activation
		$version = get_option(WP_ARCHIVEPRESS_PREFIX . "version");
		if($version == ""){
			// INSTALLATION PROCEDURE
			// 1. add new specific tables
			// a. feeds
			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

			$table_name = $this->feedTable;
			if($this->wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
				$sql = "CREATE TABLE " . $table_name . " (
  						id mediumint(9) NOT NULL AUTO_INCREMENT,
  						name VARCHAR(50) DEFAULT 'Feed Name' NOT NULL,
						url VARCHAR(200) NOT NULL,
						protocol VARCHAR(5) DEFAULT '".$this->options->defFeedProtocol."' NOT NULL,
						version VARCHAR(8),
						feed_date DATETIME NOT NULL,
						last_update DATETIME NOT NULL,
						is_comment VARCHAR(3) DEFAULT 'no' NOT NULL,
						active VARCHAR(3) DEFAULT 'yes' NOT NULL,
						last_fetched VARCHAR(200),
						UNIQUE KEY id (id)
						);";
				dbDelta($sql);
			} else {
				throw new Exception('Table' . $table_name . ' already exists');
				exit;
			}

			// b. feeds links (will help to prevent feed duplication)
			$table_name = $this->feedLinks;
		   	if($this->wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
				$sql = "CREATE TABLE " . $table_name . " (
  						id mediumint(9) NOT NULL AUTO_INCREMENT,
						feed_id mediumint(9) NOT NULL,
  						url VARCHAR(200) NOT NULL,
						is_the_one_in_use VARCHAR(3) DEFAULT 'no' NOT NULL,
						UNIQUE KEY id (id)
						);";
				dbDelta($sql);
		   	} else {
				throw new Exception('Table' . $table_name . ' already exists');
				exit;
			}

			// c. feed options
			$table_name = $this->feedOptions;
		   	if($this->wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
				$sql = "CREATE TABLE " . $table_name . " (
  						id mediumint(9) NOT NULL AUTO_INCREMENT,
						feed_id mediumint(9) NOT NULL,
  						name VARCHAR(200) NOT NULL,
						value TEXT,
						UNIQUE KEY id (id)
						);";
				dbDelta($sql);
		   	} else {
				throw new Exception('Table' . $table_name . ' already exists');
				exit;
			}
			// d. feed meta
			$table_name = $this->feedMeta;
		   	if($this->wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
				$sql = "CREATE TABLE " . $table_name . " (
  						id mediumint(9) NOT NULL AUTO_INCREMENT,
						feed_id mediumint(9) NOT NULL,
						value TEXT,
						meta_date DATETIME NOT NULL,
						UNIQUE KEY id (id)
						);";
				dbDelta($sql);
		   	} else {
				throw new Exception('Table' . $table_name . ' already exists');
				exit;
			}
		   	// e. feed users: NOW IN wp_usermeta
		   	/*
				$table_name = $this->feedUsers;
			   	if($this->wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
   					$sql = "CREATE TABLE " . $table_name . " (
	  						id mediumint(9) NOT NULL AUTO_INCREMENT,
							feed_id mediumint(9) NOT NULL,
	  						ori_username VARCHAR(200) NOT NULL,
							add_post_id mediumint(9) NOT NULL,
							add_date DATETIME NOT NULL,
							UNIQUE KEY id (id)
							);";
					dbDelta($sql);
			   	} else {
   					throw new Exception('Table' . $table_name . ' already exists');
   					exit;
   				}
			*/
			// f. log
			$table_name = $this->logTable;
		   	if($this->wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
				$sql = "CREATE TABLE " . $table_name . " (
  						id mediumint(9) NOT NULL AUTO_INCREMENT,
  						log_date DATETIME NOT NULL,
  						level VARCHAR(5) NOT NULL,
						message TEXT,
						UNIQUE KEY id (id)
						);";
				dbDelta($sql);
		   	} else {
				throw new Exception('Table' . $table_name . ' already exists');
				exit;
			}

			// 2. add wp options
			// PLUGIN OPTIONS
			add_option(WP_ARCHIVEPRESS_PREFIX . "version",				$this->options->pluginVersion);
			add_option(WP_ARCHIVEPRESS_PREFIX . "isRunning", "yes");
			add_option(WP_ARCHIVEPRESS_PREFIX . "feedsTableName",		$this->options->feedsTableName);
			add_option(WP_ARCHIVEPRESS_PREFIX . "feedLinksTableName",	$this->options->feedLinksTableName);
			add_option(WP_ARCHIVEPRESS_PREFIX . "feedMetaTableName",	$this->options->feedMetaTableName);
			add_option(WP_ARCHIVEPRESS_PREFIX . "feedOptionsTableName",	$this->options->feedOptionsTableName);
			add_option(WP_ARCHIVEPRESS_PREFIX . "feedUsersTableName",	$this->options->feedUsersTableName);
			add_option(WP_ARCHIVEPRESS_PREFIX . "logTableName",			$this->options->logTableName);
			add_option(WP_ARCHIVEPRESS_PREFIX . "cronType",				$this->options->cronType);
			add_option(WP_ARCHIVEPRESS_PREFIX . "cronKey",				urlencode(wp_generate_password( 16, false )));

			// FEED OPTIONS
			add_option(WP_ARCHIVEPRESS_PREFIX . "defFeedProtocol",		$this->options->defFeedProtocol);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defRssVersion",		$this->options->defRssVersion);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defAtomVersion",		$this->options->defAtomVersion);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defFeedFetchInt",		$this->options->defFeedFetchInt);
			add_option(WP_ARCHIVEPRESS_PREFIX . "justAddedIsActive",	$this->options->justAddedIsActive);
			add_option(WP_ARCHIVEPRESS_PREFIX . "showWhatWillDo",		$this->options->showWhatWillDo);
			add_option(WP_ARCHIVEPRESS_PREFIX . "followPermaLink",		$this->options->followPermaLink);
			add_option(WP_ARCHIVEPRESS_PREFIX . "embedMedia",			$this->options->embedMedia);
			add_option(WP_ARCHIVEPRESS_PREFIX . "keepPostAuth",			$this->options->keepPostAuth);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defAuthor",			$this->options->defAuthor);
			add_option(WP_ARCHIVEPRESS_PREFIX . "keepPostCategories",	$this->options->keepPostCategories);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defCategory",			$this->options->defCategory);
			add_option(WP_ARCHIVEPRESS_PREFIX . "tryAutoTag",			$this->options->tryAutoTag);
			add_option(WP_ARCHIVEPRESS_PREFIX . "YahooKey",				$this->options->YahooKey);
			add_option(WP_ARCHIVEPRESS_PREFIX . "useCategoriesAsTags",	$this->options->useCategoriesAsTags);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defPostStatus",		$this->options->defPostStatus);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defCommentsStatus",	$this->options->defCommentsStatus);
			add_option(WP_ARCHIVEPRESS_PREFIX . "postFetchComments",	$this->options->postFetchComments);
			add_option(WP_ARCHIVEPRESS_PREFIX . "tryTypePadStandard",	$this->options->tryTypePadStandard);
			add_option(WP_ARCHIVEPRESS_PREFIX . "areCommentsApproved",	$this->options->areCommentsApproved);
			add_option(WP_ARCHIVEPRESS_PREFIX . "htmlAllowedTags",		$this->options->htmlAllowedTags);
			add_option(WP_ARCHIVEPRESS_PREFIX . "saveContributors",		$this->options->saveContributors);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defContributorLink",	$this->options->defContributorLink);
			add_option(WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt",		$this->options->tryToFindExcerpt);

			// LOG OPTIONS
			add_option(WP_ARCHIVEPRESS_PREFIX . "defLogStatus",			$this->options->defLogStatus);
			add_option(WP_ARCHIVEPRESS_PREFIX . "defLogLevel",			$this->options->defLogLevel);
			add_option(WP_ARCHIVEPRESS_PREFIX . "log_widget_show",		$this->options->log_widget_show);
			add_option(WP_ARCHIVEPRESS_PREFIX . "log_widget_items",		$this->options->log_widget_items);


			// PRIVATE OPTIONS
			add_option(WP_ARCHIVEPRESS_PREFIX . "pluginDelIsAllowed",	$this->options->pluginDelIsAllowed);
			add_option(WP_ARCHIVEPRESS_PREFIX . "tryTypePadAttempts",	$this->options->tryTypePadAttempts);


			// 3. pages (for templating)
			$newPost = array();
			$newPost["post_status"]		= "publish";
			$newPost["post_type"]		= "page";
			$newPost["comment_status"] 	= "close";
			$newPost["post_author"] 	= 1;
			$newPost["post_content"] 	= "";
			$newPost["post_excerpt"]	= "";
			$newPost["post_title"] 		= __("Browse by blog",ARCHIVEPRESS);
			$newPost["post_name"] 		= "blogs";
			$post_id = wp_insert_post( $newPost );
			update_post_meta($post_id, "_wp_page_template", "categories.php");
			add_option(WP_ARCHIVEPRESS_PREFIX . "blogs",$post_id);

			$newPost = array();
			$newPost["post_status"]		= "publish";
			$newPost["post_type"]		= "page";
			$newPost["comment_status"] 	= "close";
			$newPost["post_author"] 	= 1;
			$newPost["post_content"] 	= "";
			$newPost["post_excerpt"]	= "";
			$newPost["post_title"] 		= __("Browse by author",ARCHIVEPRESS);
			$newPost["post_name"] 		= "authors";
			$post_id = wp_insert_post( $newPost );
			update_post_meta($post_id, "_wp_page_template", "authors.php");
			add_option(WP_ARCHIVEPRESS_PREFIX . "authors",$post_id);

			$newPost = array();
			$newPost["post_status"]		= "publish";
			$newPost["post_type"]		= "page";
			$newPost["comment_status"] 	= "close";
			$newPost["post_author"] 	= 1;
			$newPost["post_content"] 	= "";
			$newPost["post_excerpt"]	= "";
			$newPost["post_title"] 		= __("Browse by date",ARCHIVEPRESS);
			$newPost["post_name"] 		= "archives";
			$post_id = wp_insert_post( $newPost );
			update_post_meta($post_id, "_wp_page_template", "archives.php");
			add_option(WP_ARCHIVEPRESS_PREFIX . "archives",$post_id);

			$newPost = array();
			$newPost["post_status"]		= "publish";
			$newPost["post_type"]		= "page";
			$newPost["comment_status"] 	= "close";
			$newPost["post_author"] 	= 1;
			$newPost["post_content"] 	= "";
			$newPost["post_excerpt"]	= "";
			$newPost["post_title"] 		= __("Browse by tag",ARCHIVEPRESS);
			$newPost["post_name"] 		= "tags";
			$post_id = wp_insert_post( $newPost );
			update_post_meta($post_id, "_wp_page_template", "tags.php");
			add_option(WP_ARCHIVEPRESS_PREFIX . "tags",$post_id);

		} else{
			// the plugin was already installed: check if this is an update
			if((int)str_replace(".","",$version) < $this->options->pluginVersion) {
				// UPDATE PROCEDURE
				update_option(WP_ARCHIVEPRESS_PREFIX . "version", 		$this->options->pluginVersion);
			}
			update_option(WP_ARCHIVEPRESS_PREFIX . "isRunning", "yes");

			// bring user saved options inside the class (override default settings with the user's one)
			$this->refreshClassOptions();
		}

	}

    /**
     * Plugin Deactivation
     */
	public function Deactivate(){
		// STOP cron tab jobs
		update_option(WP_ARCHIVEPRESS_PREFIX . "isRunning", "no");
	}

    /**
     * Plugin deletion
     */
	public function Remove(){
	
		require_once(ABSPATH . "/wp-admin/includes/user.php");
	
		if($this->options->pluginDelIsAllowed == ArchivePressOption::YES){
			// get last user options (useful to get table names and other settings)
			$this->refreshClassOptions();

			// delete everything related to the plugin
			// OPTIONS
			delete_option(WP_ARCHIVEPRESS_PREFIX . "version");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "isRunning");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "feedsTableName");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "feedLinksTableName");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "feedMetaTableName");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "feedOptionsTableName");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "feedUsersTableName");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "logTableName");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "blogs");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "authors");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "archives");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "tags");

			// FEED OPTIONS
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defFeedProtocol");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defRssVersion");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defAtomVersion");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defFeedFetchInt");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "justAddedIsActive");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "showWhatWillDo");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "followPermaLink");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "embedMedia");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "keepPostAuth");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defAuthor");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "keepPostCategories");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defCategory");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "tryAutoTag");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "YahooKey");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "useCategoriesAsTags");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defPostStatus");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defCommentsStatus");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "postFetchComments");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "tryTypePadStandard");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "areCommentsApproved");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "htmlAllowedTags");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "saveContributors");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defContributorLink");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "tryToFindExcerpt");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "cronType");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "cronKey");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "cron");

			// LOG OPTIONS
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defLogStatus");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "defLogLevel");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "log_widget_show");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "log_widget_items");

			// PRIVATE OPTIONS
			delete_option(WP_ARCHIVEPRESS_PREFIX . "pluginDelIsAllowed");
			delete_option(WP_ARCHIVEPRESS_PREFIX . "tryTypePadAttempts");


			// POSTS, POST METADATA AND AUTHORS
			// 1. find archivePress posts
			$myrows = $this->wpdb->get_results("SELECT post_id FROM ".$this->wpdb->postmeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."ori_media_link' GROUP BY post_id ", ARRAY_A );
			if($myrows) {
				foreach($myrows as $row){
					// 2. delete post and everything related
					$this->deletePost((int)$row["post_id"]);
				}
			}

			// 3. post authors
			$myrows = $this->wpdb->get_results("SELECT user_id FROM ".$this->wpdb->usermeta." WHERE meta_key = '".WP_ARCHIVEPRESS_PREFIX."ori_username' GROUP BY user_id ", ARRAY_A );
			if($myrows) {
				foreach($myrows as $row){
					wp_delete_user((int)$row["user_id"] );
				}
			}

			// TABLES
			$this->wpdb->query("DROP TABLE ".$this->feedTable."");
			$this->wpdb->query("DROP TABLE ".$this->feedLinks."");
			$this->wpdb->query("DROP TABLE ".$this->feedOptions."");
			$this->wpdb->query("DROP TABLE ".$this->feedMeta."");
			$this->wpdb->query("DROP TABLE ".$this->feedUsers."");
			$this->wpdb->query("DROP TABLE ".$this->logTable."");

			// IMPORTANT: right now categories, tags and contributors ARE NOT DELETED
		}
		// otherwise the user will just remove the plugin files,
		// but nothing is lost!
	}
}
?>